// BasePanel.cpp : implementation file
//

#include "stdafx.h"
#include "kwclientcore.h"
#include "BasePanel.h"
#include "BaseSurface.h"
#include "MainPanel.h"
#include "Client.h"

#include "CommonLib\PaintingUtility.h"

#include "MonitoringUnitLib\BaseCoalMineUnit.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

COLORREF ColorScheme::GetCaptionColor(int nWidth, int nIndex) const
{
  BYTE nTop;
  BYTE nBottom;

  nTop = GetRValue(m_crCaption);
  nBottom = GetRValue(m_crGradientCaption);
  BYTE R = nTop+nIndex*(nBottom-nTop)/nWidth;

  nTop = GetGValue(m_crCaption);
  nBottom = GetGValue(m_crGradientCaption);
  BYTE G = nTop+nIndex*(nBottom-nTop)/nWidth;

  nTop = GetBValue(m_crCaption);
  nBottom = GetBValue(m_crGradientCaption);
  BYTE B = nTop+nIndex*(nBottom-nTop)/nWidth;

  return RGB(R, G, B);
}

/////////////////////////////////////////////////////////////////////////////
// CBasePanel

CBasePanel::CBasePanel():
m_nCoalMineId(0),
m_strMonUnitId(""),
m_pActiveSurface(NULL),
m_nPanelType(PT_UNKNOWN)
{
  if (m_nGDIResourceCounter == 0)
  {
    m_pFont = new CFont;
    m_pFont->CreateFont(-12, 0, 0, 0, FW_THIN, false, false, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Tahoma");

  }
  m_nGDIResourceCounter++;
}

CBasePanel::~CBasePanel()
{
  m_nGDIResourceCounter--;
  if (m_nGDIResourceCounter == 0)
  {
    m_pFont->DeleteObject();
    delete m_pFont;
  }
}


BEGIN_MESSAGE_MAP(CBasePanel, CWnd)
	//{{AFX_MSG_MAP(CBasePanel)
	ON_WM_PAINT()
	ON_WM_CREATE()
	ON_WM_LBUTTONDOWN()
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_GETMINMAXINFO()
	ON_WM_MOUSEWHEEL()
	//}}AFX_MSG_MAP
  ON_COMMAND(IDC_PANEL_CLOSE, OnPanelClose)
END_MESSAGE_MAP()

CFont * CBasePanel::m_pFont = NULL;
int CBasePanel::m_nGDIResourceCounter = 0;

/////////////////////////////////////////////////////////////////////////////
// CBasePanel message handlers

bool CBasePanel::Create(const CString& strWindowName, CWnd * pParentWnd, const CRect& rect, bool bVisible)
{
  return CWnd::CreateEx(0, 
                        AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(NULL, IDC_ARROW)), 
                        strWindowName, 
                        WS_POPUP | WS_THICKFRAME | (bVisible?WS_VISIBLE:0),
                        rect, 
                        pParentWnd, 
                        0);
}

void CBasePanel::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
  CRect rect;
  GetClientRect(&rect);
  dc.FillRect(&rect, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

  GetCaptionRect(&rect);
  for (int i = rect.top; i < rect.bottom;i++)
  {
    COLORREF crColor = m_ColorScheme.GetCaptionColor(rect.Height(), i-rect.top);
    dc.FillSolidRect(rect.left, i, rect.Width(), 1, crColor);
  }

  GetLabelRect(&rect);
  for (i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    CRect rcLabel(rect.right-(m_Surfaces.size()-i)*80, rect.top+2, rect.right-(m_Surfaces.size()-i-1)*80, rect.bottom);
    CString strName;
    pSurface->GetWindowText(strName);
    if (pSurface == m_pActiveSurface)
    {
      PaintingUtility::PaintBitmap(dc, rcLabel.TopLeft(), m_ColorScheme.m_nActiveLabelBmpId);
    }
    else
    {
      PaintingUtility::PaintBitmap(dc, rcLabel.TopLeft(), m_ColorScheme.m_nInactiveLabelBmpId);
    }
    CFont * pOldFont = dc.SelectObject(m_pFont);
    int nOldBkMode = dc.SetBkMode(TRANSPARENT);
    rcLabel.DeflateRect(16, 0, 0, 0);
    dc.DrawText(strName, &rcLabel, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
    dc.SetBkMode(nOldBkMode);
    dc.SelectObject(pOldFont);
  }

  GetCaptionRect(&rect);
  CFont * pOldFont = dc.SelectObject(m_pFont);
  int nOldBkMode = dc.SetBkMode(TRANSPARENT);
  COLORREF crOldText = dc.SetTextColor(RGB(255, 255, 255));
  CString str;
  GetWindowText(str);
  dc.TextOut(rect.left+2, rect.top+2, str);
  dc.SetTextColor(crOldText);
  dc.SetBkMode(nOldBkMode);
  dc.SelectObject(pOldFont);

  Paint(dc);

	// Do not call CWnd::OnPaint() for painting messages
}

int CBasePanel::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
  bool bSuccess = m_btnClose.Create("Close", BS_PUSHBUTTON | BS_OWNERDRAW | WS_VISIBLE, CRect(0, 0, 0, 0), this, IDC_PANEL_CLOSE);
  ASSERT(bSuccess);
  m_btnClose.LoadBitmaps(IDB_BITMAP_CLOSEUP, IDB_BITMAP_CLOSEDOWN);

  CreateSurfaces();

  BaseCoalMineUnit * pCoalMineUnit = Client::Instance()->GetCoalMineUnitById(GetCoalMineId());
  if (pCoalMineUnit)
  {
    for (int i = 0;i < m_Surfaces.size();i++)
    {
      CBaseSurface * pSurface = m_Surfaces[i];
      pSurface->UpdateDefinitionDisplay(pCoalMineUnit);
    }
  }

	return 0;
}

void CBasePanel::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
  CBaseSurface * pSurface = GetpSurfaceByPoint(point);
  if (pSurface)
  {
    if (pSurface->CanBeActivated()) ActivateSurface(pSurface);
  }
  else
  {
    CRect rect;
    GetCaptionRect(&rect);
    if (rect.PtInRect(point) && !IsZoomed())
    {
	    SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, (LPARAM)(LPPOINT)&point);
    }
  }

	CWnd::OnLButtonDown(nFlags, point);
}

CBaseSurface * CBasePanel::GetpSurfaceByPoint(const CPoint& point) const
{
  CRect rect;
  GetLabelRect(&rect);
  for (int i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    CRect rcLabel(rect.right-(m_Surfaces.size()-i)*80, rect.top+2, rect.right-(m_Surfaces.size()-i-1)*80, rect.bottom);
    if (rcLabel.PtInRect(point))
    {
      return pSurface;
    }
  }
  return NULL;
}

void CBasePanel::GetCaptionRect(LPRECT lpRect) const
{
  CRect rect;
  GetClientRect(&rect);
  *lpRect = rect;
  lpRect->bottom = lpRect->top+kCaptionHeight;
}

void CBasePanel::GetSurfaceRect(LPRECT lpRect) const
{
  CRect rect;
  GetClientRect(&rect);
  *lpRect = rect;
  lpRect->top += kCaptionHeight;
}

void CBasePanel::GetLabelRect(LPRECT lpRect) const
{
  CRect rect;
  GetCaptionRect(&rect);
  *lpRect = rect;
  lpRect->right -= 16+10;
}

void CBasePanel::OnSize(UINT nType, int cx, int cy) 
{
	CWnd::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
  CRect rect;
  GetCaptionRect(&rect);
  rect.left = rect.right-1-16;
  rect.top += 2;
  rect.right = rect.left+16;
  rect.bottom = rect.top+14;
  m_btnClose.MoveWindow(rect);

  GetSurfaceRect(&rect);
	for (int i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    pSurface->MoveWindow(rect);
  }

  Invalidate();
}

void CBasePanel::OnDestroy() 
{
	CWnd::OnDestroy();
	
	// TODO: Add your message handler code here
  DestroyAllSurfaces();
	g_pMainPanel->RemovePanel(this);
}

void CBasePanel::PostNcDestroy() 
{
	// TODO: Add your specialized code here and/or call the base class
	delete this;

	CWnd::PostNcDestroy();
}

void CBasePanel::AddSurface(CBaseSurface * pSurface)
{
  m_Surfaces.push_back(pSurface);
}

void CBasePanel::DestroyAllSurfaces()
{
  for (int i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    pSurface->DestroyWindow();
  }
  m_Surfaces.clear();
}

void CBasePanel::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
  CRect rect;
  GetCaptionRect(&rect);
  if (rect.PtInRect(point))
  {
    ShowWindow(IsZoomed()?SW_RESTORE:SW_SHOWMAXIMIZED);
  }
	
	CWnd::OnLButtonDblClk(nFlags, point);
}

void CBasePanel::OnPanelClose()
{
  ShowWindow(SW_HIDE);
}

void CBasePanel::ActivateSurface(int nIndex)
{
  ASSERT(nIndex < m_Surfaces.size());

  if (m_pActiveSurface != m_Surfaces[nIndex])
  {
    ShowSurface(m_pActiveSurface, false);
    m_pActiveSurface = m_Surfaces[nIndex];
    ShowSurface(m_pActiveSurface, true);
    Invalidate();
  }
}

void CBasePanel::ActivateSurface(CBaseSurface * pSurface)
{
  if (m_pActiveSurface != pSurface)
  {
    ShowSurface(m_pActiveSurface, false);
    m_pActiveSurface = pSurface;
    ShowSurface(m_pActiveSurface, true);
    Invalidate();
  }
}

void CBasePanel::ShowSurface(CBaseSurface * pSurface, bool bShow)
{
  if (pSurface)
  {
    pSurface->ShowWindow(bShow?SW_SHOW:SW_HIDE);
    if (bShow) pSurface->BringWindowToTop();
  }
}

void CBasePanel::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
{
	// TODO: Add your message handler code here and/or call default
  GetMinMaxInfo(lpMMI);
	
	CWnd::OnGetMinMaxInfo(lpMMI);
}

void CBasePanel::UpdateDisplay()
{
  for (int i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    pSurface->UpdateDisplay();
  }
}

void CBasePanel::UpdateDefinitionDisplay(BaseCoalMineUnit * pCoalMineUnit)
{
  for (int i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    pSurface->UpdateDefinitionDisplay(pCoalMineUnit);
  }
}

void CBasePanel::UpdateDataDisplay(BaseCoalMineUnit * pCoalMineUnit, BaseMonitoringUnit * pMonitoringUnit)
{
  for (int i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    pSurface->UpdateDataDisplay(pCoalMineUnit, pMonitoringUnit);
  }
}

BaseCoalMineUnit * CBasePanel::GetCoalMineUnit() const
{
  return Client::Instance()->GetCoalMineUnitById(GetCoalMineId());
}

void CBasePanel::GetCoalMineUnitAndMonUnit(BaseCoalMineUnit *& pCoalMineUnit, BaseMonitoringUnit *& pMonitoringUnit) const
{
  Client::Instance()->GetCoalMineUnitAndMonUnitById(GetCoalMineId(), GetMonUnitId(), pCoalMineUnit, pMonitoringUnit);
}

BOOL CBasePanel::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	// TODO: Add your message handler code here and/or call default
	m_pActiveSurface->HandleMouseWheel(nFlags, zDelta, pt);

	return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}

void CBasePanel::ApplyOptions(DWORD dwOptionPagesMask)
{
  for (int i = 0;i < m_Surfaces.size();i++)
  {
    CBaseSurface * pSurface = m_Surfaces[i];
    pSurface->ApplyOptions(dwOptionPagesMask);
  }
}
